package com.framework.bdf4j.msg.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.framework.bdf4j.comm.SpringContextHolder;
import com.framework.bdf4j.comm.web.WebUtil;
import com.framework.bdf4j.msg.constant.PublicConstant;
import com.framework.bdf4j.msg.entity.domain.SysMessages;
import com.framework.bdf4j.msg.entity.domain.SysMsgDept;
import com.framework.bdf4j.msg.entity.domain.SysMsgReceiver;
import com.framework.bdf4j.msg.entity.domain.SysMsgResult;
import com.framework.bdf4j.msg.entity.domain.SysMsgRole;
import com.framework.bdf4j.msg.entity.dto.SysMessagesQueryDTO;
import com.framework.bdf4j.msg.entity.dto.SysMessagesSaveDTO;
import com.framework.bdf4j.msg.entity.dto.SysMessagesUpdateDTO;
import com.framework.bdf4j.msg.entity.vo.SysMessagesReceiveVo;
import com.framework.bdf4j.msg.entity.vo.SysMessagesVo;
import com.framework.bdf4j.msg.entity.vo.SysUserVO;
import com.framework.bdf4j.msg.mapper.SysMessagesMapper;
import com.framework.bdf4j.msg.sender.EMailMessageSender;
import com.framework.bdf4j.msg.sender.Sender;
import com.framework.bdf4j.msg.sender.SmsSender;
import com.framework.bdf4j.msg.sender.WebSocketMessageSender;
import com.framework.bdf4j.msg.service.SysMessagesService;
import com.framework.bdf4j.msg.service.SysMsgDeptService;
import com.framework.bdf4j.msg.service.SysMsgReceiverService;
import com.framework.bdf4j.msg.service.SysMsgResultService;
import com.framework.bdf4j.msg.service.SysMsgRoleService;
import com.framework.bdf4j.msg.util.DtoEntityUtil;
import com.framework.bdf4j.sysadm.entity.SysLog;
import com.framework.bdf4j.sysadm.service.SysUserService;
import com.framework.bdf4j.sysadm.vo.SecurityUser;
import com.google.common.base.Splitter;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 消息发送服务
 *
 * @author shan.deng
 * @date 2020-07-15 16:06:44
 */
@Service
public class SysMessagesServiceImpl extends ServiceImpl<SysMessagesMapper, SysMessages> implements SysMessagesService {


    @Resource
    private SysMsgReceiverService sysMsgReceiverService;

    @Resource
    private SysMessagesMapper sysMessagesMapper;

    @Resource
    private SysMsgResultService sysMsgResultService;

    @Resource
    private SysMsgRoleService sysMsgRoleService;

    @Resource
    private SysMsgDeptService sysMsgDeptService;
    
    @Resource
    private SysUserService sysUserService;


    /**
     * 查询我接受的消息
     * @param page
     * @param sysMessagesQueryDTO
     * @return
     */
    @Override
    public IPage<SysMessagesReceiveVo> pageMessageMyReceived(Page page, SysMessagesQueryDTO sysMessagesQueryDTO) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            SecurityUser scauser = (SecurityUser)authentication.getPrincipal();
            QueryWrapper<SysMessagesQueryDTO> ew = new QueryWrapper<SysMessagesQueryDTO>();
            ew.eq("DEL_FLAG", "0").eq("msg_status", "1");
            this.setParm(ew, sysMessagesQueryDTO);
            return sysMessagesMapper.pageMessageMyReceived(page,ew,sysMessagesQueryDTO,scauser.getUserId());
        }
        return page;
    }

    /**
     * 查询自己发送的消息
     * @param page
     * @param sysMessagesQueryDTO
     * @return
     */
    @Override
    public IPage<SysMessagesVo> pageMessageMySend(Page page, SysMessagesQueryDTO sysMessagesQueryDTO) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            SecurityUser scauser = (SecurityUser)authentication.getPrincipal();
            QueryWrapper<SysMessagesQueryDTO> ew = new QueryWrapper<SysMessagesQueryDTO>();
            this.setParm(ew, sysMessagesQueryDTO);
            ew.eq("DEL_FLAG", "0").eq("CREATE_BY", scauser.getUserId());
            sysMessagesMapper.pageMessageMySend(page,ew);
        }
        return page;
    }

    /**
     *  根据消息Id查询详情
     * @param id
     * @return
     */
    @Override
    public SysMessagesVo getMessagesById(Integer id) {
        return sysMessagesMapper.getMessagesResultById(id);
    }

    /**
     * 根据消息Id查询收到的消息详情
     * @param id
     * @return
     */
    @Override
    public SysMessagesReceiveVo getReceivedMessagesById(Integer id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            SecurityUser scauser = (SecurityUser)authentication.getPrincipal();
            return sysMessagesMapper.getReceivedMessagesById(id,scauser.getUserId());
        }
        return null;
    }

    /**
     * 保存消息
     * @param sysMessagesSaveDTO
     * @return
     */
    @Override
    @Transactional
    public boolean saveMessages(SysMessagesSaveDTO sysMessagesSaveDTO) {

        SysMessages sysMessages = DtoEntityUtil.trans(sysMessagesSaveDTO, SysMessages.class);

        sysMessages.setMsgStatus(PublicConstant.MSG_STATUS_NEW);
        String value = StringUtils.join(sysMessagesSaveDTO.getSendChannels(), ",");
        sysMessages.setSendChannel(value);

        sysMessages.setCreateBy(WebUtil.getHttpCurrentUserId());
        sysMessages.setCreateTime(new Date());
        sysMessages.setUpdateTime(new Date());
        save(sysMessages);
        if(PublicConstant.RECEIVER_RANGE_GLOBAL.equals(sysMessagesSaveDTO.getReceiveRange())) {
            sysMsgReceiverService.saveAllPerson(sysMessages.getMsgId());
        }else {
            sysMsgRoleService.saveSysMsgRoleBatch(sysMessages.getMsgId(),sysMessagesSaveDTO.getSysMsgRoles());

            sysMsgDeptService.saveSysMsgDeptBatch(sysMessages.getMsgId(),sysMessagesSaveDTO.getSysMsgDepts());

            sysMsgReceiverService.saveReceiverBatch(sysMessages.getMsgId(),sysMessagesSaveDTO.getSysMsgRecievers());
        }
        return true;
    }

    /**
     *  修改消息
     * @param sysMessagesUpdateDTO
     * @return
     */
    @Override
    @Transactional
    public boolean updateMessages(SysMessagesUpdateDTO sysMessagesUpdateDTO) {

        SysMessages sysMessages = this.getById(sysMessagesUpdateDTO.getMsgId());
        SysMessages trans = DtoEntityUtil.trans(sysMessagesUpdateDTO, SysMessages.class);
        trans.setSendChannel(StringUtils.join(sysMessagesUpdateDTO.getSendChannels(), ","));
        trans.setUpdateBy(WebUtil.getHttpCurrentUserId());
        if(PublicConstant.MSG_STATUS_SEND.equals(sysMessages.getMsgStatus())) {
            throw new RuntimeException("该消息已被发送,不能修改");
        }
        this.updateById(trans);   
        
        //删除发送人的表
        sysMsgReceiverService.remove(Wrappers.<SysMsgReceiver>update().lambda().eq(SysMsgReceiver::getMsgId,sysMessages.getMsgId()));

        //删除部门选择的表
        sysMsgDeptService.remove(Wrappers.<SysMsgDept>update().lambda().eq(SysMsgDept::getMsgId,sysMessages.getMsgId()));

        //删除角色选择的表
        sysMsgRoleService.remove(Wrappers.<SysMsgRole>update().lambda().eq(SysMsgRole::getMsgId,sysMessages.getMsgId()));
        
        if(PublicConstant.RECEIVER_RANGE_GLOBAL.equals(sysMessagesUpdateDTO.getReceiveRange())) {
            sysMsgReceiverService.saveAllPerson(sysMessages.getMsgId());
        }else {
            sysMsgRoleService.saveSysMsgRoleBatch(sysMessages.getMsgId(),sysMessagesUpdateDTO.getSysMsgRoles());

            sysMsgDeptService.saveSysMsgDeptBatch(sysMessages.getMsgId(),sysMessagesUpdateDTO.getSysMsgDepts());

            sysMsgReceiverService.saveReceiverBatch(sysMessages.getMsgId(),sysMessagesUpdateDTO.getSysMsgRecievers());
        }
        return true;
    }

    /**
     * 删除消息
     * @param id
     * @return
     */
    @Override
    @Transactional
    public boolean deleteMessages(Integer id) {

        //删除消息基础表中的内容
        this.removeById(id);

        //删除发送人的表
        sysMsgReceiverService.remove(Wrappers.<SysMsgReceiver>update().lambda().eq(SysMsgReceiver::getMsgId,id));

        //还要删除结果表中的记录
        sysMsgResultService.remove(Wrappers.<SysMsgResult>update().lambda().eq(SysMsgResult::getMsgId,id));

        //删除部门选择的表
        sysMsgDeptService.remove(Wrappers.<SysMsgDept>update().lambda().eq(SysMsgDept::getMsgId,id));

        //删除角色选择的表
        sysMsgRoleService.remove(Wrappers.<SysMsgRole>update().lambda().eq(SysMsgRole::getMsgId,id));

        return true;
    }

    @Override
    public boolean sendMessage(SysMessages sysMessages) {

        SysMessagesSaveDTO sysMessagesSaveDTO = DtoEntityUtil.trans(sysMessages, SysMessagesSaveDTO.class);
        sysMessagesSaveDTO.setSendChannels(Splitter.on(",").trimResults().splitToList(sysMessages.getSendChannel()));
        checkAndSend(sysMessages.getMsgId(),sysMessagesSaveDTO);
        return Boolean.TRUE;
    }

    /**
     * 校验是否立即发送
     * @param sysMessagesSaveDTO
     */
    private void checkAndSend(Integer msgId,SysMessagesSaveDTO sysMessagesSaveDTO) throws RuntimeException{

        if(!PublicConstant.SEND_TIME_IMMEDIATE.equals(sysMessagesSaveDTO.getSendType())) {
            return;
        }

        List<Sender> senders = new ArrayList<>();

        sysMessagesSaveDTO.getSendChannels().forEach(channel -> {
            if(PublicConstant.SEND_TYPE_SMS.equals(channel)) {
                SmsSender smsSender = SpringContextHolder.getBean(SmsSender.class);
                senders.add(smsSender);
            }
            if(PublicConstant.SEND_TYPE_EMAIL.equals(channel)) {
                EMailMessageSender eMailMessageSender = SpringContextHolder.getBean(EMailMessageSender.class);
                senders.add(eMailMessageSender);
            }
            if(PublicConstant.SEND_TYPE_NET.equals(channel)) {
                WebSocketMessageSender webSocketMessageSender = SpringContextHolder.getBean(WebSocketMessageSender.class);
                senders.add(webSocketMessageSender);
            }
        });
        senders.stream().forEach(sender -> {
            List<SysUserVO> users = sysUserService.getUserInfoByMsgId(msgId);
            sender.send(msgId, sysMessagesSaveDTO, users);
        });
        
        SysMessages sysMessages = new SysMessages();
        sysMessages.setMsgId(msgId);
        sysMessages.setMsgStatus(PublicConstant.MSG_STATUS_SEND);
        sysMessages.setUpdateTime(new Date());
        this.updateById(sysMessages);
    }
    
    private QueryWrapper<SysMessagesQueryDTO> setParm(QueryWrapper<SysMessagesQueryDTO> ew, SysMessagesQueryDTO msg){
    	ew.eq(StrUtil.isNotBlank(msg.getMsgType()), "msg_type", msg.getMsgType())
    	.like(StrUtil.isNotBlank(msg.getMsgTitle()), "msg_title", msg.getMsgTitle())
    	.like(StrUtil.isNotBlank(msg.getMsgContent()), "msg_content", msg.getMsgContent())
    	.eq(StrUtil.isNotBlank(msg.getMsgStatus()), "msg_status", msg.getMsgStatus())
    	.eq(StrUtil.isNotBlank(msg.getSendChannel()), "send_channel", msg.getSendChannel())
    	.eq(StrUtil.isNotBlank(msg.getSendType()), "send_type", msg.getSendType());
    	return ew;
    }
}
